package com.cwh.service.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cwh.entity.Baoxiaobill;
import com.cwh.service.BaoxiaobillService;
import com.cwh.service.WorkFlowService;
import com.cwh.utils.UUIDUtils;
import com.cwh.utils.WorkFlowDirgamUtils;

import org.apache.commons.lang.StringUtils;

@Service
public class WorkFlowServiceImpl implements WorkFlowService {
	
	@Autowired
	private RepositoryService repositoryService;
	
	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	private TaskService taskService;
	
	@Autowired
	private HistoryService historyService;
	
	@Autowired
	private FormService formService;
	
	@Autowired
	private BaoxiaobillService baoxiaobillService;
	
	//zip发布流程
	@Override
	public void saveNewDeploy(InputStream in, String processName) {
		//将普通的file流转换成ZipInputStream流
		ZipInputStream zipInputStream = new ZipInputStream(in);
		//部署流程
		this.repositoryService
		.createDeployment()
		.addZipInputStream(zipInputStream)
		.name(processName)
		.deploy();
		/*
		在下面三张表插入数据
		act_re_procdef（流程定义表）
		act_re_deployment（部署对象表）
		act_ge_bytearray（资源文件表） 
		 */
	}
	
	//查看部署表act_re_deployment
	@Override
	public List<Deployment> findReDeploymentList() {
		List<Deployment> deploymentList = repositoryService
		.createDeploymentQuery()
		//根据id排序
		.orderByDeploymentId()
		//降序排序
		.desc()
		.list();
		return deploymentList;
		
	}
	
	//查看流程表信息act_re_procdef
	@Override
	public List<ProcessDefinition> findReProcdefList() {
		List<ProcessDefinition> processDefinitionList = repositoryService
		.createProcessDefinitionQuery()
		//根据id排序
		.orderByProcessDefinitionId()
		//降序排序
		.desc()
		.list();
		return processDefinitionList;
	}
	
	//删除根据部署id删除部署流程
	@Override
	public void deleteDeploymentById(String deploymentId) {
		/*
		 是否开启级联删除 true 强行删除，即使有流程正在运行，也要删除掉！
		根据 deploymentId从下面三个表删除有关记录
		act_re_procdef（流程定义表）
		act_re_deployment（部署对象表）
		act_ge_bytearray（资源文件表） 
		 */
		repositoryService.deleteDeployment(deploymentId, true);
		
	}
	
	//我的待办事务 根据用户名称查act_ru_task表 
	@Override
	public List<Task> findRuTaskListByUsername(String username) {
		List<Task> taskList = taskService.createTaskQuery()
		//代办人名字为用户名
		.taskAssignee(username)
		//根据id排序
		.orderByTaskId()
		.desc()
		.list();
		return taskList;
	}
	
	//启动流程
	@Override
	public void saveStartProcess(String processKey, Integer baoxiaobillId,String username) {
		
		//businessKey=流程图id+"."+报销表单记录id
		String businessKey = processKey+"."+baoxiaobillId;
		
		//流程变量
		Map<String, Object> variables= new HashMap<String, Object>();
		variables.put("userId",username);//存储用户名
		variables.put("businessKey",businessKey);//存储businessKeyKey
		runtimeService.startProcessInstanceByKey(processKey, businessKey, variables);
		
		
	}
	//根据taskId获取报销(baoxiaobill)记录
	@Override
	public Baoxiaobill findBaoxiaoBillByTaskId(String taskId) {
		//根据taskId获取act_ru_task的记录 
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//获取act_ru_task的记录 的PROC_INST_ID
		String processInstanceId = task.getProcessInstanceId();
		//根据PROC_INST_ID获取act_ru_exection记录
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		//获取act_ru_exection记录的businessKey
		String businessKey = processInstance.getBusinessKey();
		String[] split = businessKey.split("\\.");
		String baoxiaobillId = "";
		if(StringUtils.isNotBlank(split[1])) {//判空
			baoxiaobillId=split[1];
		}

		return baoxiaobillService.findBaoxiaobillById(Integer.parseInt(baoxiaobillId));
	}
	
	//根据taskId获取历史审批(act_hi_comment)记录
	@Override
	public List<Comment> findCommentByTaskId(String taskId) {
		//根据taskId获取act_ru_task的记录 
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//获取act_ru_task的记录 PROC_INST_ID
		String processInstanceId = task.getProcessInstanceId();
		//根据 PROC_INST_ID获取act_hi_comment的记录
		List<Comment> commentList = taskService.getProcessInstanceComments(processInstanceId);
		return commentList;
	}
	//根据taskId获取当前活动结点的线对象集合,前端渲染
	@Override
	public List<String> findOutComeListByTaskId(String taskId) {
		//返回存放连线的名称集合
		List<String> list = new ArrayList<String>();
		//1.根据taskId查找act_ru_task的记录
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//2.根据act_ru_task的记录获取PRO_DEF_ID
		String processDefinitionId = task.getProcessDefinitionId();
		//3.根据PRO_DEF_ID查找act_re_def的记录
		ProcessDefinitionEntity processDefinitionEntity =(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
		
		//4.根据act_ru_task的记录获取PRO_INST_ID
		String processInstanceId = task.getProcessInstanceId();
		//5.根据PRO_INST_ID获取act_ru_exection的记录
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()
		.processInstanceId(processInstanceId)//使用流程实例ID查询
		.singleResult();
		
		//获取当前活动节点的id
		String activityId = pi.getActivityId();
		//根据活动结点id获取当获取节点对象
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
		//获取当前活动完成后连线的名称
		List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
		if(pvmList!=null&&pvmList.size()>0) {
			for(PvmTransition pvm: pvmList) {
				//获取线的名字
				String name = (String)pvm.getProperty("name");
				if(StringUtils.isNotBlank(name)) {//name!=null
					list.add(name);
				}else {
					list.add("默认提交");
				}
			}
		}
		return list;
	}
	
	//办理任务
	@Override
	public void submitTask(long id, String taskId, String comment, String outcome, String username) {
		
		//根据taskId查找act_ru_task记录
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		
		//设置当前批注对应的审批人
		Authentication.setAuthenticatedUserId(username);
		
		//根据act_ru_task表查找PRO_INST_ID,comment
		String processInstanceId = task.getProcessInstanceId();
		
		/*
		 * 添加批注功能
		 * 在act_hi_comment中插入taskId,
		 */
		taskService.addComment(taskId,processInstanceId , comment);
		
		/*
		 * 推进流程
		 * 根据活动结点选择的线的name推动相应的路线
		 */
		HashMap<String,Object> variables = new HashMap<>();
		if(outcome!=null&&!outcome.equals("默认提交")) {
			variables.put("message", outcome);
			taskService.complete(taskId,variables);//任务id,流程变量
			System.out.println("推动了:"+outcome);
		}else {			
			taskService.complete(taskId);
			System.out.println("推动了默认的");
		}
		//获取当前流程实例对象 查 act_ru_execution是否存在，下面根据这里判断流程是否走完
		ProcessInstance  processInstance= runtimeService
		.createProcessInstanceQuery()
		.processInstanceId(processInstanceId)
		.singleResult();
		
		//流程已经结束
		if(processInstance==null) {
			//根据baoxiaobillId去查询出当前这个leaveBill
			Baoxiaobill baoxiaobill = baoxiaobillService.findBaoxiaobillById((int)id);
			baoxiaobill.setState(2);
			//更新实体
			baoxiaobillService.updateBaoxiaobill(baoxiaobill);
			
		}
		
		
		
	}
	//查看审核记录  使用报销单id，查找历史批注信息
	@Override
	public List<Comment> findCommentByBaoxiaoBillId(long id) {
		//组装bussinessKey
		String bussinessKey=WorkFlowDirgamUtils.DIRGAM_ID+"."+id;
		//通过bussinessKey在查找act_hi_proinst记录
		HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery()
		.processInstanceBusinessKey(bussinessKey)
		.singleResult();
		//通过act_hi_proins的id在act_hi_comment
		List<Comment>  commentList=null;
		if(pi!=null) {
			commentList= taskService.getProcessInstanceComments(pi.getId());
		}
		return commentList;
	}
	
	//获取资源文件表（act_ge_bytearray）中资源图片输入流InputStream
	@Override
	public InputStream findImageInputStream(String deploymentId, String imageName) {
		
		return repositoryService.getResourceAsStream(deploymentId, imageName);
	}

	//通过taskId查询act_re_procdef记录
	@Override
	public ProcessDefinition findProcessDefinitionByTaskId(String taskId) {
		//根据taskId查询act_ru_task表记录
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//根据act_ru_task表查询PROC_DEF_ID
		String processDefinitionId = task.getProcessDefinitionId();
		//根据PROC_DEF_ID作为id查询act_re_procdef记录
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
		.processDefinitionId(processDefinitionId)
		.singleResult();
		
		return processDefinition;
	}
	
	//查看当前活动，获取当期活动对应的坐标x,y,width,height，将4个值存放到Map<String,Object>中
	@Override
	public Map<String, Object> findCoordingByTask(String taskId) {
		//存放坐标
		Map<String, Object> map = new HashMap<String,Object>();
		//根据taskId查询act_ru_task
		Task task = taskService.createTaskQuery()//
					.taskId(taskId)//使用任务ID查询
					.singleResult();
		//获取PROC_DEF_ID ，通过查询act_ru_task
		String processDefinitionId = task.getProcessDefinitionId();
		//获取流程定义的实体对象（对应.bpmn文件中的数据） 
		//通过PROC_DEF_ID 查询act_re_procdef记录
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId);
		//获取PROC_INST_ID,通过查询act_ru_task
		String processInstanceId = task.getProcessInstanceId();
		//根据PROC_INST_ID查询act_ru_exection记录
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()//创建流程实例查询
											.processInstanceId(processInstanceId)//使用流程实例ID查询
											.singleResult();
		//获取当前活动结点的ID
		String activityId = pi.getActivityId();
		//获取当前活动对象
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活动ID
		//获取坐标
		map.put("x", activityImpl.getX());
		map.put("y", activityImpl.getY());
		map.put("width", activityImpl.getWidth());
		map.put("height", activityImpl.getHeight());
		return map;
	}
	
	//通过bussinessKey查找act_ru_task表
	@Override
	public Task findTaskByBussinessKey(String bUSSINESS_KEY) {
		Task task = taskService.createTaskQuery().processInstanceBusinessKey(bUSSINESS_KEY).singleResult();
		return task;
	}
	

	
	
	
	

}
